package com.xiyuan.smartutils.client.http;

import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.client.domain.FormData;
import com.xiyuan.smartutils.constants.HttpConstants;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

/**
 * the description for class WebUtil
 *
 * @author xiyuan-lgz 2023-03-04 @version v1.0.0 新建与整理
 */
public class WebUtils implements HttpConstants {
    private static final Map<String, String> EMPTY_HEADER = new HashMap<>(0);
    
    private static <T extends HttpClient> T init(T client, Map<String, String> headerMap, String contentType) {
        if (headerMap != null) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                client.addRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        
        return client.addRequestProperty(Validates.isNotBlank(contentType), _CONTENT_TYPE_, contentType);
    }
    
    /**
     * 提交数据
     *
     * @param url       提交地址
     * @param form      form表单
     * @param headerMap 自定义请求头
     * @return Http调用结果
     */
    public static HttpResult post(String url, FormData form, Map<String, String> headerMap) {
        HttpPost client = init(new HttpPost(url), headerMap, null).setFormData(form);
        return client.execute().getResult();
    }
    
    /**
     * 提交数据
     *
     * @param url       提交地址
     * @param paramMap  参数表
     * @param headerMap 自定义请求头
     * @return HttpResult
     */
    public static HttpResult post(String url, Map<String, ?> paramMap, Map<String, String> headerMap) {
        HttpPost client = init(new HttpPost(url), headerMap, null);
        if (paramMap != null) {
            for (Map.Entry<String, ?> entry : paramMap.entrySet()) {
                client.addParam(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
        
        return client.execute().getResult();
    }
    
    public static HttpResult post(String url, Map<String, ?> paramMap) {
        return post(url, paramMap, EMPTY_HEADER);
    }
    
    
    /**
     * 提交数据
     *
     * @param url         提交地址
     * @param data        contentType 编码后的字符串
     * @param contentType mineType 类型
     * @param headerMap   自定义请求头
     * @return HttpResult
     */
    public static HttpResult post(String url, String data, String contentType, Map<String, String> headerMap) {
        HttpPost client = init(new HttpPost(url), headerMap, contentType);
        return client.setQueryString(data).execute().getResult();
    }
    
    
    /**
     * 提交数据
     *
     * @param url         提交地址
     * @param data        contentType 编码后的字符串
     * @param contentType mineType 类型
     * @return HttpResult
     */
    public static HttpResult post(String url, String data, String contentType) {
        return post(url, data, contentType, EMPTY_HEADER);
    }
    
    /**
     * 提交数据
     *
     * @param url  提交地址
     * @param data application/x-www-form-urlencoded 编码字符串
     * @return HttpResult
     */
    public static HttpResult post(String url, String data) {
        return new HttpPost(url).setQueryString(data).execute().getResult();
    }
    
    public static HttpResult postJson(String url, String data) {
        return post(url, data, _APPLICATION_JSON_, EMPTY_HEADER);
    }
    
    public static HttpResult postJson(String url, String data, Map<String, String> headerMap) {
        return post(url, data, _APPLICATION_JSON_, headerMap == null ? EMPTY_HEADER : headerMap);
    }
    
    public static HttpResult postJson(String url, String data, Supplier<Map<String, String>> supplier) {
        return post(url, data, _APPLICATION_JSON_, supplier.get());
    }
    
    public static <T> HttpResult postJson(String url, T data, JsonSerializer<T, String> serializer) {
        if (serializer == null) {
            throw new NullPointerException("serializer is null");
        }
        return post(url, serializer.serialize(data), _APPLICATION_JSON_, EMPTY_HEADER);
    }
    
    public static <T> HttpResult postJson(String url, T data, JsonSerializer<T, String> serializer, Map<String, String> headers) {
        if (serializer == null) {
            throw new NullPointerException("serializer is null");
        }
        return post(url, serializer.serialize(data), _APPLICATION_JSON_, headers);
    }
    
    @FunctionalInterface
    public static interface JsonSerializer<T, R> {
        /**
         * 序列化内容
         *
         * @param r 数据对象
         * @return 返回结果
         */
        public R serialize(T r);
    }
    
    public static HttpResult get(String url) {
        return get(url, null);
    }
    
    public static HttpResult get(String url, Map<String, String> headerMap) {
        return init(new HttpGet(url), headerMap, null).execute().getResult();
    }
    
    public static HttpResult delete(String url) {
        return delete(url, null);
    }
    
    public static HttpResult delete(String url, Map<String, String> headerMap) {
        return init(new HttpDelete(url), headerMap, null).execute().getResult();
    }
    
    public static HttpResult put(String url) {
        return put(url, null, null, null, null);
    }
    
    public static HttpResult put(String url, Map<String, String> headerMap) {
        return put(url, null, null, null, headerMap);
    }
    
    public static HttpResult put(String url, String data, String mimeType) {
        return put(url, data, mimeType, null, null);
    }
    
    public static HttpResult put(String url, String data, String mimeType, Map<String, String> headerMap) {
        return put(url, data, mimeType, null, headerMap);
    }
    
    public static HttpResult put(String url, String data, String mimeType, String encoding) {
        return put(url, data, mimeType, encoding, null);
    }
    
    public static HttpResult put(String url, String data, Map<String, String> headerMap) {
        return put(url, data, null, null, headerMap);
    }
    
    public static HttpResult put(String url,
                                 String data,
                                 String mimeType,
                                 String encoding,
                                 Map<String, String> headerMap) {
        HttpPut client = new HttpPut(url);
        client.setEncoding(encoding);
        if (data == null) data = "";
        return init(client, headerMap, mimeType).setBytes(data.getBytes()).execute().getResult();
    }
    
    
}
